import utils as utils
import os
import parser as parser
import counter_data as counter
reload(parser)
reload(utils)
reload(counter)

#globals
LOCAL_DIR = r"C:\Users\Danny\Documents\lol_team_tool"
SUMMONERS_DIR = os.path.join(LOCAL_DIR, "summoners")
CACHE_DIR = os.path.join(LOCAL_DIR, "cache")
MATCH_LIST_DIR = os.path.join(LOCAL_DIR, "match_lists")

COUNTERS = counter.COUNTERS
CHAMP_ROLE = {'evelynn': 'm-dps', 'zed': 'm-dps', 'nunu': 'fighter', 'swain': 'mage', 'taric': 'support', 'nasus': 'fighter', 'graves': 'r-dps', 'nocturne': 'm-dps', 'shaco': 'm-dps', 'leesin': 'fighter', 'draven': 'r-dps', 'renekton': 'fighter', 'nidalee': 'fighter', 'kassadin': 'mage', 'sona': 'support', 'cassiopeia': 'mage', 'skarner': 'fighter', 'malzahar': 'mage', 'amumu': 'tank', 'khazix': 'm-dps', 'olaf': 'fighter', 'sivir': 'r-dps', 'riven': 'fighter', 'nami': 'support', 'kogmaw': 'r-dps', 'gangplank': 'fighter', 'syndra': 'mage', 'poppy': 'fighter', 'volibear': 'fighter', 'kennen': 'mage', 'ryze': 'mage', 'gragas': 'fighter', 'garen': 'fighter', 'diana': 'm-dps', 'karthus': 'mage', 'jayce': 'fighter', 'sion': 'fighter', 'elise': 'mage', 'alistar': 'tank', 'leblanc': 'mage', 'ezreal': 'r-dps', 'fiddlesticks': 'mage', 'lux': 'mage', 'fiora': 'm-dps', 'twistedfate': 'mage', 'darius': 'fighter', 'kayle': 'support', 'hecarim': 'fighter', 'anivia': 'mage', 'yorick': 'fighter', 'jax': 'm-dps', 'jarvaniv': 'fighter', 'ashe': 'r-dps', 'malphite': 'fighter', 'irelia': 'fighter', 'annie': 'mage', 'twitch': 'r-dps', 'tryndamere': 'm-dps', 'janna': 'support', 'blitzcrank': 'tank', 'talon': 'm-dps', 'vayne': 'r-dps', 'xinzhao': 'm-dps', 'katarina': 'm-dps', 'chogath': 'tank', 'shen': 'tank', 'drmundo': 'fighter', 'caitlyn': 'r-dps', 'missfortune': 'r-dps', 'morgana': 'mage', 'viktor': 'mage', 'brand': 'mage', 'warwick': 'fighter', 'corki': 'r-dps', 'maokai': 'tank', 'heimerdinger': 'mage', 'urgot': 'r-dps', 'tristana': 'r-dps', 'galio': 'tank', 'vladimir': 'mage', 'orianna': 'mage', 'masteryi': 'm-dps', 'soraka': 'support', 'varus': 'r-dps', 'fizz': 'mage', 'veigar': 'mage', 'rengar': 'm-dps', 'nautilus': 'tank', 'lulu': 'support', 'pantheon': 'm-dps', 'trundle': 'fighter', 'ahri': 'mage', 'shyvana': 'fighter', 'udyr': 'fighter', 'zyra': 'mage', 'mordekaiser': 'mage', 'zilean': 'mage', 'rammus': 'tank', 'rumble': 'mage', 'wukong': 'fighter', 'monkeyking': 'fighter', 'sejuani': 'tank', 'xerath': 'mage', 'ziggs': 'mage', 'singed': 'tank', 'karma': 'support', 'akali': 'm-dps', 'leona': 'tank', 'teemo': 'r-dps'}

MY_USER_NAME = "dannyLol3"
MY_ID = "27365916"

ROLES = ["dps", "tank", "fighter", "support", "mage"]

#ROLE_HIGH_RATING = {'tank': 202.11005993150684, 'support': 626.26974887467429, 'dps': 520.93994107744118, 'fighter': 340.46486456400737, 'mage': 407.80643447461625}
#ROLE_LOW_RATING = {'tank': 14.460986780677183, 'support': 57.821418316482777, 'dps': 83.77113358190374, 'fighter': 50.48282995129869, 'mage': 33.816868649801798}
#ROLE_AVE_RATING = {'tank': 69.432965507726422, 'support': 221.08337093525105, 'dps': 211.08989557050609, 'fighter': 128.21350701810107, 'mage': 168.07649859432735}

ROLE_HIGH_RATING = {'tank': 279.6, 'support': 541.36, 'dps': 705.22, 'fighter': 381.24, 'mage': 462.34}
ROLE_LOW_RATING ={'tank': 14.460986780677183, 'support': 102.34, 'dps': 55.255570194268543, 'fighter': 58.52, 'mage': 40.0}
ROLE_AVE_RATING ={'tank': 98.232993853975614, 'support': 235.04407018260119, 'dps': 259.29580633831046, 'fighter': 159.12870247482095, 'mage': 211.23486459059404}

DEFAULT_RANKING = -.5

##
#Analysis Interface
##
def get_role(champ):
	if champ in ROLES:
		return champ
	role = CHAMP_ROLE.get(champ)
	if role == None:
		print "could not find role!"
		role = "dps"
	elif role == "m-dps" or role == "r-dps":
		role = "dps"
	return role

def get_counter(champ):
	counter_list = COUNTERS.get(champ)
	if champ == "aaa":
		return []
	if not counter_list:
		print "warning: could not find counter for ", champ
		return []
	return counter_list

class Summoner():
	def __init__(self, id = MY_ID, data_cache = True, soup_cache = True):
		self.id = id
		self.data  = parser.get_summoner_data(id, data_cache, soup_cache)
		self.season_stats = self.data["stats"]

	def get_champs_by_role(self, role = None, season="all"):
		champs = []
		if season == "all":
			for k in self.season_stats.keys():
				for c in self.season_stats[k]:
					champs.append(c)
		else:
			_stats = self.season_stats.get(season)
			if not _stats:
				return None
			for c in self.season_stats[season]:
				champs.append(c)
		if not role:
			return champs
		
		champs_by_role = []
		for c in champs:
			_c_role = c.get("role")
			if _c_role:
				if c["role"] == role:
					champs_by_role.append(c)
		return champs_by_role

	def get_champ(self,name, season="all"):
		champs = []
		if season == "all":
			for k in self.season_stats.keys():
				for c in self.season_stats[k]:
					champs.append(c)
		else:
			_stats = self.season_stats.get(season)
			if not _stats:
				return None
			for c in self.season_stats[season]:
				champs.append(c)
		for c in champs:
			if c["name"] == name:
				return c
		return None

	def get_name(self):
		name = self.data.get("meta")
		if not name:
			name = "undefined"
		return name

	def get_dps_rating(self, season = "all"):
		return self.get_role_rating("dps", season)

	def get_fighter_rating(self, season = "all"):
		return self.get_role_rating("fighter", season)

	def get_mage_rating(self, season = "all"):
		return self.get_role_rating("mage", season)

	def get_support_rating(self, season="all"):
		return self.get_role_rating("support", season)

	def get_tank_rating(self, season="all"):
		return self.get_role_rating("tank", season)

	def get_role_percision_ratings(self, season = "all", threshold = 0):
		roles = ["dps", "fighter", "mage", "support", "tank"]
		percision_rating = []
		for role in roles:
			champs = self.get_champs_by_role(role, season)
			if not champs:
				continue
			percision = 0
			for c in champs:
				percision += c["played"]
			if percision > threshold:
				percision_rating.append([percision, role])
		percision_rating.sort()
		percision_rating.reverse()
		return percision_rating

	def get_role_rating(self, role, season):
		kill_ratio, assists, assists_ratio, cs, kills, div = 0, 0, 0, 0, 0, 0
		champs = self.get_champs_by_role(role, season)
		if not champs:
			return None
		for c in champs:
			kill_ratio+= c["kill_ratio"]
			cs += c["cs"]
			kills += c["kills"]
			assists += c["assists"]
			assists_ratio += c["assists_ratio"]
			div +=1
				#print c["name"], c["kill_ratio"], c["kills"], c["deaths"]
		if div == 0:
			return None
		kill_ratio, cs, kills, assists, assists_ratio = kill_ratio/div, cs/div, kills/div, assists/div, assists_ratio/div
		gold_score = (kills*12) + cs + (assists*4)
		if role == "support":
			rating = gold_score * assists_ratio
		else:
			rating = gold_score * kill_ratio
		return rating

	def get_champ_rating(self, name, season = "all"):
		kill_ratio, assists, assists_ratio, cs, kills, div = 0, 0, 0, 0, 0, 0
		champ = self.get_champ(name, season)
		if not champ:
			return None
		kill_ratio = champ["kill_ratio"]
		cs = champ["cs"]
		kills = champ["kills"]
		assists = champ["assists"]
		assists_ratio += champ["assists_ratio"]
		kill_ratio, cs, kills, assists, assists_ratio = kill_ratio, cs, kills, assists, assists_ratio
		gold_score = (kills*12) + cs + (assists*4)
		role = get_role(name)
		if not role:
			role = "dps"
		if role == "support":
			rating = gold_score * assists_ratio
		else:
			rating = gold_score * kill_ratio
		return rating

	def get_champ_percision(self, champ):
		roles = ["dps", "fighter", "mage", "support", "tank"]
		percision_rating = []
		for role in roles:
			champs = self.get_champs_by_role(role, season)
			if not champs:
				continue
			percision = 0
			for c in champs:
				percision += c["played"]
			if percision > threshold:
				percision_rating.append([percision, role])
		percision_rating.sort()
		percision_rating.reverse()
		return percision_rating

	def get_percision_by_role(self, role, plist):
		for p in plist:
			if p[1] == role:
				return p[0]
		return None

	def auto_analysis(self, champ_name = None):
		season_3_roles = self.get_role_percision_ratings("season_3", threshold = 10)
		season_all_roles = self.get_role_percision_ratings("all", threshold = 10)
		ranking = {}
		for r in ROLES:
			_season = "season_3"
			_tmp = self.get_percision_by_role(r, season_3_roles)
			if not _tmp:
				_tmp = self.get_percision_by_role(r, season_all_roles)
				_season = "all"
			if not _tmp:
				ranking[r] = DEFAULT_RANKING
			else:
				_rating = self.get_role_rating(r, _season)
				h,a,l = ROLE_HIGH_RATING[r], ROLE_AVE_RATING[r], ROLE_LOW_RATING[r]
				if _rating < a:
					per = -1+(_rating-l)/(a-l)
				if _rating > a:
					per = 0+(_rating-a)/(h-a)
				ranking[r] = per
		champ_rating = None
		champ_ranking = None
		if champ_name:
			champ_data = self.get_champ(champ_name, "season_3")
			if champ_data:
				if champ_data["played"] > 10:
					champ_rating = self.get_champ_rating(champ_name, season = "season_3")
			if not champ_rating:
				champ_data = self.get_champ(champ_name, "all")
				if champ_data:
					if champ_data["played"] > 10:
						champ_rating = self.get_champ_rating(champ_name, season = "all")
		if champ_rating:
			role = get_role(champ_name)
			if role:
				_rating = champ_rating
				h,a,l = ROLE_HIGH_RATING[role], ROLE_AVE_RATING[role], ROLE_LOW_RATING[role]
				if _rating < a:
					per = -1+(_rating-l)/(a-l)
				if _rating > a:
					per = 0+(_rating-a)/(h-a)
				champ_ranking = per


		return ranking, champ_ranking

class MatchList():
	def __init__(self, id):
		self.id = id
		self.data = None
		self.match_list_file = os.path.join(MATCH_LIST_DIR, self.id)
		if os.path.isfile(self.match_list_file):
			self.data = utils.unpickle_data(self.match_list_file)

	def update(self, cache = True, match_type = "Ranked Solo 5v5"):
		soup = parser.get_summoner_soup_page(self.id, cache = cache)
		if not soup:
			return
		matches = parser.get_match_history_dict(soup, self.id, match_type = match_type)
		if not self.data:
			self.data = {}
			self.data["matches"] = matches
			self.data["meta"] = parser.get_meta_from_summoner_page(soup)
			utils.pickle_data(self.data, self.match_list_file)
			return
		matches.reverse()
		for m in matches:
			if not self.get_entry_by_date(m["date"]):
				self.data["matches"].insert(0, m)
		utils.pickle_data(self.data, self.match_list_file)

	def get_entry_by_date(self, date, match_list = None):
		if match_list == None:
			match_list = self.data["matches"]
		for m in match_list:
			if m["date"] == date:
				return m
		return None
def counter_occurance(x, _list):
	count = 0
	for i in _list:
		if i == x:
			count += 1
	return count

def get_counter_score(ally_champs, enemy_champs):
	ally_rating, enemy_rating = 0, 0
	def _do(champ_list, against_champ_list):
		rating = 0
		message = ""
		for c in champ_list:
			counters = get_counter(c)
			for c_champ in counters:
				if c_champ in against_champ_list:
					rating += 1
					message += "%s counters %s\n"%(c_champ, c)
		return rating, message
	ally_rating, ally_message = _do(ally_champs, enemy_champs)
	enemy_rating, enemy_message = _do(enemy_champs, ally_champs)
	return 10-ally_rating, 10-enemy_rating, ally_message, enemy_message



#team predictions
def team_predict(players, enemy_champs, show_all=True):
	#players = [('evelynn', '488081'), ('nunu', '35879541'), ('taric', '20125062'), ('nasus', '18992448'), ('graves', '24120850')]
	#enemy_champs = ["kassadin", "sona", "cassiopeia", "skarner", "malzahar"]
	#players = [('sona', '27738547'), ('warwick', 'two'), ('xerath', 'three'), ('caitlyn', 'four'), ('kayle', "27335516")]
	#enemy_champs = ["aaa", "aaa", "aaa", "aaa", "aaa"]
	total = 0
	ally_champs = []
	n = 0
	print "-----------------------------------------------------------------"
	for p in players:
		msg = ""
		if not p[1]:
			total += -.5
			print "no allie, adding -.5 to total"
			continue
		_sum = Summoner(p[1], True, True)
		print "\n"
		ranking, champ_ranking = _sum.auto_analysis(p[0])

		if p[0]:
			if p[0] in ROLES:
				current_role = p[0]
			else:
				current_role = get_role(p[0])
			role_ranking = ranking[current_role]
			msg += "as %s: %.2f\n"%(current_role, role_ranking)
			if champ_ranking:
				msg+= "as %s: %.2f\n"%(p[0], champ_ranking)
			if not p[0] in ROLES:
				ally_champs.append(p[0])
		else:
			role_ranking = -.5
		if champ_ranking:
			total += champ_ranking
		else:
			total += role_ranking
		n+=1
		if show_all:
			_m = ""
			for k,v in ranking.items():
				_m += " %s:%.2f "%(k, v)
			msg += "ALL ROLES:%s"%(_m)
		print _sum.get_name()
		print msg
	print "\n"
	msg = ""
	if n == 5:
		msg += "team rating: %.2f"
	else:
		msg += "INACURATE team rating: %.2f"
	print msg%total
	print "\n"
	res = get_counter_score(ally_champs, enemy_champs)
	print "\n"
	print res[0], res[1]
	print "allies:"
	print res[2]
	print "enemies:"
	print res[3]

#_sum = Summoner("27661714")
#print _sum.auto_analysis()

#historic analysis
'''
for m in w_ml.data["matches"][0:10]:
'''
def historic_analysis(id = MY_ID, matches_count = 1, do_team_predict = True, game_type = "Ranked Solo 5v5"):
	ml = MatchList(id)
	ml.update(True)

	m_len = len(ml.data["matches"])
	if m_len < matches_count:
		matches_count = m_len
	prediction_count = 0
	success = 0
	for m in ml.data["matches"][0:matches_count]:
		teams = m["team"]
		#print m["outcome"]
		if m["outcome"] == "win": outcome = 0
		else: outcome = 1
		ally_champs, enemy_champs = [], []
		name = []
		allie_team = []
		team_rankings = []
		prev_total = None
		prev_feeder_total = None
		output_txt = ""
		for i, t in enumerate([teams["allies"], teams["enemies"]]):
			total = 0
			feeder_total = 0
			for p in t:
				if i == 0:
					ally_champs.append(p[0])
					allie_team.append((p[0], p[1]))
				else:
					enemy_champs.append(p[0])
				try:
					_sum = Summoner(p[1], True, True)
				except:
					_sum = Summoner(p[1], False, True)

				name.append(_sum.get_name())
				ranking, champ_ranking = _sum.auto_analysis(p[0])
				ranking = ranking[get_role(p[0])]
				role = get_role(p[0])
			 	if champ_ranking:
			 		ranking = champ_ranking
			 	if ranking < -.6:
			 		#ranking = ranking*ranking
			 		feeder_total += 1
			 	total += ranking

			_o = ""
			_append = True
			if outcome == i:
				_o = "@"
			if prev_total:
				if not prev_total > total:
					_append = False

			if _append:
				team_rankings.append([total, _o, feeder_total])
			else:
				team_rankings.insert(0, [total, _o, feeder_total])

			prev_total = total
			prev_feeder_total = feeder_total

			output_txt += _o+"\t" + str(total) + "\n"

		#print output_txt
		_tr = team_rankings
		_do_predict = False
		if _tr[0][0] > .5:
			_do_predict = True

		if _do_predict: prediction_count +=1
		if _tr[0][1] == "@":
			if _do_predict:
				success +=1
				_tr[0][1] = "***"


		print "%.2f - %i - %s \n%.2f - %i - %s"%(_tr[0][0],_tr[0][2],_tr[0][1],
									_tr[1][0],_tr[1][2], _tr[1][1])
		res = get_counter_score(ally_champs, enemy_champs)
		#print res[0], res[1]
		#print name
		if do_team_predict:
			team_predict(allie_team, enemy_champs, show_all=True)
			print "##############################################################"
			print "##############################################################"
		print ""
	if not prediction_count == 0:
		predict_ratio = success/float(prediction_count)
		print "predict_accuracy: %.2f"%(predict_ratio)
	else: 
		print "no predictions"
	return success, prediction_count

def mutli_history_analysis(ids = []):
	success, total_matches = 0, 0
	for id in ids:
		_s, _t = historic_analysis(id, 10, False)
		success += _s
		total_matches += _t
	predict_ratio = success/float(total_matches)
	print "PREDICTION ACCURACY: %.2f"%(predict_ratio)
	print "%i/%i"%(success, total_matches)

#
#reload(lol);lol.mutli_history_analysis(["32763225", "24682068", "20615541", "29830524", "34683760", "20976333"])
#